package com.hp.bon.sgw.wh.channel.handler;

import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.hp.bon.sgw.Constants;
import com.hp.bon.sgw.bean.XmlMessage;
import com.hp.bon.sgw.core.BuzProcessorManager;
import com.hp.bon.sgw.core.CallParam;
import com.hp.bon.sgw.core.channel.SoapChannel;
import com.hp.bon.sgw.core.channel.handler.IAsynCallHandler;
import com.hp.bon.sgw.threads.TaskManager;
import com.hp.bon.sgw.wh.service.UserResourceConfigService;
import com.hp.bon.sgw.wh.utils.LogUtil;
import com.hp.bon.sgw.wh.utils.ResultCodeUtil;
import com.hp.ocs.diameter.message.*;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.HttpException;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.RequestEntity;
import org.apache.commons.httpclient.methods.StringRequestEntity;
import org.simpleframework.http.Request;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @ClassName: QryBillHandle
 * @Description: 欠费查询
 */
public class QryBillHandle2 implements IAsynCallHandler {
	private static final Logger _log = LoggerFactory.getLogger(QryBillHandle2.class);

    private static final Object XmlMessage = null;
    private long startTime;
    private Request request;
    private PrintStream printStream;
    private JSONObject requestObject;
    private UserResourceConfigService userResourceConfigService ;
    public QryBillHandle2(PrintStream printStream, JSONObject requestObject, Request request, long startTime) {
        this.printStream = printStream;
        this.requestObject = requestObject;
        this.startTime = startTime;
        this.request = request;
    }

	@Override
	public int getProtocolType() {
		return 0;
	}

	@Override
	public void onCallResult(CallParam callParam) {
        requestObject.put("jfEndTime",System.currentTimeMillis());
		XmlMessage ack = null;
		Object response = null;
		if (callParam.getResponse() != null) {
			response = callParam.getResponse();
		} else if (callParam.getRecvResponse() != null) {
			response = callParam.getRecvResponse();
		}
		if (response == null) {
			int _retcodeTmp = callParam.getRetCode() == 3002 ? 11202 : callParam.getRetCode();
			ack = SoapChannel.createERRAnwser(callParam.getSessionId(), _retcodeTmp, callParam.getResultMsg());
			callParam.setServiceResultCode(_retcodeTmp);// 11203
		} else {
			if (response instanceof Message) {// CCA -> XML
				ack = BuzProcessorManager.getInstance().convertMessageToAck(callParam);
			} else if (response instanceof XmlMessage) {
				ack = (XmlMessage) response;
			} else {
				_log.warn("unknown response type:" + callParam.getResponse().getClass().getName());
			}
		}
		try {
			String respXML = convertResponseString((Message) response, callParam.getServiceResultCode());
			byte[] resp = respXML.getBytes("UTF-8");
			ack.setLength(resp.length);
			ack.setMsgTime(System.currentTimeMillis());
			printStream.write(resp);
			printStream.close();
			callParam.setResponse(ack);
            //记录到日志
            LogUtil.saveLogToABM(request,respXML,startTime,requestObject);
			TaskManager.taskProcess(callParam);
			_log.info("http response2(cfq) " + respXML);
		}   catch (Exception e) {
			_log.info("convertResponseString2 IOException,msg=" , e);
		}
	}
	

	
	
	/**
	 * 返回最终json格式数据
	 * @param answer
	 * @param serviceResultCode
	 * @return
	 */
	private String convertResponseString(Message answer, int serviceResultCode) {
		_log.info("QryBillHandle2 serviceResultCode = {}", serviceResultCode);
		String response = "";
		Map<String, Object> data = new HashMap<String, Object>();
		Map<String, Object> map = getAvpsFromMessage(answer);//DCC返回结果

		if(map == null){
			// 解析下游返回数据出错
			data.put("resultCode", "-1");
			data.put("resultMsg", "查询失败");
		}else if(serviceResultCode != 0){
			// 如果返回了错误码，则将错误信息转给用户
			data.put("resultCode", serviceResultCode);
			data.put("resultMsg", "");
		}else{
            data.putAll(map);
		}
        String newCode = ResultCodeUtil.updateResultCode(data.get("resultCode"), userResourceConfigService.getValue("api_resultCode"), userResourceConfigService.getValue("api_defaultResult"));
        data.put("resultCode", newCode);
		Gson gson = new Gson();
		response = gson.toJson(data);
		return response;
	}

	
	/**
	 * 处理CCA结果
	 * @param answer
	 * @return
	 */
	public Map<String, Object> getAvpsFromMessage(Message answer) {
		Map<String, Object> map = new HashMap<String, Object>();
		try {
			AVP avp = answer.find(Constants.DIAMETER_AVP_SERVICE_INFOMATION, Constants.DIAMETER_VENDOR_3GPP);
			AVP_Grouped avpServiceInfomation = new AVP_Grouped(avp);
			AVP[] avps = avpServiceInfomation.queryAVPs();
            List<Map<String,Object>> feeBillingCycle=new ArrayList<Map<String, Object>>();
			for (AVP avpData : avps) {
				if (avpData.code() == 80407  && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
					map.put("resultMsg", String.valueOf(new AVP_UTF8String(avpData).queryValue()));
				}
				if (avpData.code() == 80125  && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
					map.put("accNbr", String.valueOf(new AVP_UTF8String(avpData).queryValue()));
				}
                if (avpData.code() == 80119  && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                    map.put("shouldCharge", new AVP_Integer32(avpData).queryValue());
                }
                if (avpData.code() == 80118  && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                    map.put("validBalance", new AVP_Integer32(avpData).queryValue());
                }
                if (avpData.code() == 80121  && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                    map.put("previousChange", new AVP_Integer32(avpData).queryValue());
                }
                if (avpData.code() == 80108  && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                    map.put("acctName", String.valueOf(new AVP_UTF8String(avpData).queryValue()));
                }
                if (avpData.code() == 80107  && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                    map.put("acctId", new AVP_Unsigned64(avpData).queryValue());
                }
                if (avpData.code() == 20631  && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                    map.put("resultCode", String.valueOf(new AVP_Unsigned32(avpData).queryValue()));
                }
                if (avpData.code() == 80116  && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                    map.put("due", new AVP_Integer32(avpData).queryValue());
                }
                if (avpData.code() == 80123  && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                    map.put("currentChange", new AVP_Integer32(avpData).queryValue());
                }
                if (avpData.code() == 80117  && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                    map.put("derateDue", new AVP_Integer32(avpData).queryValue());
                }
                //feeBillingCycle
                if (avpData.code() == 80109  && avpData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                    Map<String, Object> fbc_Map = new HashMap<String, Object>();
                    List<Map<String,Object>> acctItemGroupList=new ArrayList<Map<String, Object>>();
                    //feeBillingCycle
                    AVP_Grouped fbc_AVP = new AVP_Grouped(avpData);
                    for (AVP fbcData : fbc_AVP.queryAVPs()) {
                        if (fbcData.code() == 80111   && fbcData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                            Map<String, Object> aig_Map = new HashMap<String, Object>();
                            List<Map<String,Object>> acctItemType=new ArrayList<Map<String, Object>>();
                            //acctItemGroupList
                            AVP_Grouped aig_AVP = new AVP_Grouped(fbcData);
                            for (AVP aigData : aig_AVP.queryAVPs()) {
                                if (aigData.code() == 80112   && aigData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                                    //Enumerated 按 Integer32  取 AVP_Integer32
                                    aig_Map.put("acctItemGroupId", String.valueOf(new AVP_Integer32(aigData).queryValue()));
                                }
                                if (aigData.code() == 80113    && aigData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                                    Map<String, Object> ait_Map = new HashMap<String, Object>();
                                    //acctItemType
                                    AVP_Grouped ait_AVP = new AVP_Grouped(aigData);
                                    for (AVP aitData : ait_AVP.queryAVPs()) {
                                        if (aitData.code() == 80114    && aitData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                                            ait_Map.put("acctItemTypeName", String.valueOf(new AVP_UTF8String(aitData).queryValue()));
                                        }
                                        if (aitData.code() == 80115    && aitData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                                            ait_Map.put("acctItemCharge", new AVP_Integer32(aitData).queryValue());
                                        }
                                    }
                                    acctItemType.add(ait_Map);
                                }
                            }
                            aig_Map.put("acctItemType",acctItemType);
                            acctItemGroupList.add(aig_Map);
                        }
                        if (fbcData.code() == 80110    && fbcData.vendorID() == Constants.DIAMETER_VENDOR_CT) {
                            fbc_Map.put("billingCycleId", new AVP_Unsigned32(fbcData).queryValue());
                        }
                    }
                    fbc_Map.put("acctItemGroupList",acctItemGroupList);
                    feeBillingCycle.add(fbc_Map);
                }
			}
            map.put("feeBillingCycle",feeBillingCycle);
		} catch (Exception e) {
			map = null;
			_log.error("getAvpsFromMessage Exception error,msg=" ,e);
		}
		return map;
	}

	
	/**
	 * 调用详单查询webservice接口
	 * @param param
	 * @return
	 */
	private String sendWebService(String param,String url) {
		int timeOut = 5000;
		String resp = "";
		PostMethod post = new PostMethod(url);
		try {
			RequestEntity requestEntity = new StringRequestEntity(param, "text/xml", "UTF-8");
			post.setRequestEntity(requestEntity);
			HttpClient client = new HttpClient();
			client.getHttpConnectionManager().getParams().setConnectionTimeout(5 * 1000);
			client.getHttpConnectionManager().getParams().setSoTimeout(timeOut);
			try {
				client.executeMethod(post);
			} catch (HttpException e) {
				_log.info("===========webservice call timeout===============" + url);
				e.printStackTrace();
			} catch (IOException e) {

				return "";
			}
			try {
				_log.info("===========完成webservice===============" + resp);
				resp = post.getResponseBodyAsString();
			} catch (IOException e) {
				_log.info("===========webservice call timeout===============" + url);
				return "";
			}
		} catch (UnsupportedEncodingException e) {
			_log.info("===========webservice call timeout===============" + url);
			e.printStackTrace();
		}
		return resp;
	}
	
	
}
